/**
 * ReportGear(2011)
 */
package com.reportgear.designer.pane.headerfooter;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.JPanel;
import javax.swing.JViewport;
import javax.swing.Scrollable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import com.reportgear.report.model.headerfooter.HFElement;

/**
 * 面板-页眉页脚-内部组件容器
 * 
 * @version 1.0 2011-4-22
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since Report 1.0
 */
public class HFContainer extends JPanel implements Scrollable {
	/**
	 * UID
	 */
	private static final long serialVersionUID = 8219878731040094120L;
	private List<HFComponent> hfComponentList = new ArrayList<HFComponent>();
	private ChangeListener contentChangeListener = null;

	private ActionListener moveLeftActionListener = new ActionListener() {
		public void actionPerformed(ActionEvent evt) {
			Object src = evt.getSource();
			if (!(src instanceof HFComponent)) {
				return;
			}

			moveLeftHFComponent((HFComponent) src);
		}
	};

	private ActionListener moveRightActionListener = new ActionListener() {
		public void actionPerformed(ActionEvent evt) {
			Object src = evt.getSource();
			if (!(src instanceof HFComponent))
				return;

			moveRightHFComponent((HFComponent) src);
		}
	};

	private ActionListener deleteActionListener = new ActionListener() {
		public void actionPerformed(ActionEvent evt) {
			Object src = evt.getSource();
			if (!(src instanceof HFComponent)) {
				return;
			}

			removeHFComponent((HFComponent) src);
		}
	};

	public HFContainer() {
		this.setEnabled(true);
		this.setLayout(new FlowLayout(FlowLayout.LEFT));
	}

	public void setEnabled(boolean enabled) {
		super.setEnabled(enabled);
		if (enabled)
			setBackground(UIManager.getColor("TextArea.background"));
		else
			setBackground(SystemColor.control);
	}

	private void refreshLayout() {
		removeAll();

		for (HFComponent c : this.hfComponentList) {
			this.add(c);
		}

		contentChanged();
	}

	public ChangeListener getContentChangeListener() {
		return this.contentChangeListener;
	}

	public void setContentChangeListener(ChangeListener listner) {
		this.contentChangeListener = listner;
	}

	private void contentChanged() {
		if (this.contentChangeListener == null)
			return;

		ChangeEvent changeEvt = new ChangeEvent(this);
		this.contentChangeListener.stateChanged(changeEvt);
	}

	public void populate(List<HFElement> elements) {
		this.hfComponentList.clear();
		for (HFElement component : elements) {
			this.addHFComponent(new HFComponent(component));
		}

		refreshLayout();
	}

	public List<HFElement> update() {
		List<HFElement> hfList = new ArrayList<HFElement>();

		for (HFComponent c : this.hfComponentList) {
			hfList.add(c.getHFElement());
		}

		return hfList;
	}

	public void addHFComponent(HFComponent component) {
		addHFComponent(-1, component);
	}

	public void addHFComponent(int index, HFComponent component) {
		if ((index <= -1) || (index > this.hfComponentList.size()))
			this.hfComponentList.add(component);
		else
			this.hfComponentList.add(index, component);

		component.setMoveLeftActionListener(this.moveLeftActionListener);
		component.setMoveRightActionListener(this.moveRightActionListener);
		component.setDeleteActionListener(this.deleteActionListener);
		component.setContentChangeListener(getContentChangeListener());

		refreshLayout();
	}

	public void removeHFComponent(HFComponent component) {
		if (!(this.hfComponentList.contains(component))) {
			return;
		}

		this.hfComponentList.remove(component);
		refreshLayout();
	}

	public void moveLeftHFComponent(HFComponent component) {
		int index = this.hfComponentList.indexOf(component);
		if (index > 0) {
			Collections.swap(this.hfComponentList, index - 1, index);
		}

		refreshLayout();
	}

	public void moveRightHFComponent(HFComponent component) {
		int index = this.hfComponentList.indexOf(component);
		if (index < this.hfComponentList.size() - 1) {
			Collections.swap(this.hfComponentList, index, index + 1);
		}

		refreshLayout();
	}

	@Override
	public Dimension getPreferredScrollableViewportSize() {
		return this.getPreferredSize();
	}

	@Override
	public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
		switch (orientation) {
		case SwingConstants.VERTICAL:
			return (visibleRect.height / 10);
		case SwingConstants.HORIZONTAL:
			return (visibleRect.width / 10);
		}
		throw new IllegalArgumentException("无效的方向: " + orientation);
	}

	@Override
	public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
		switch (orientation) {
		case SwingConstants.VERTICAL:
			return visibleRect.height;
		case SwingConstants.HORIZONTAL:
			return visibleRect.width;
		}
		throw new IllegalArgumentException("无效的方向: " + orientation);
	}

	@Override
	public boolean getScrollableTracksViewportWidth() {
		if (getParent() instanceof JViewport)
			return (getParent().getWidth() > getPreferredSize().width);
		return false;
	}

	@Override
	public boolean getScrollableTracksViewportHeight() {
		if (getParent() instanceof JViewport)
			return (getParent().getHeight() > getPreferredSize().height);
		return false;
	}
}